﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using UniRlv.COL;
using UniRlv.UI.Main.Widget;
using UniRlv.Utility;
using UniRlv.Utility.Extend;

namespace UniRlv.UI.Main.WarerHourseIn
{
    public partial class FrmDataDeal : UniRlv.UI.Main.FrmBase
    {
        List<string> codes1 = new List<string>();
        List<string> codes2 = new List<string>();
        List<string> codes3 = new List<string>();
        List<string> codes4 = new List<string>();
        FrmProcessBar progBar = null;
        private System.ComponentModel.BackgroundWorker backgroundWorker1;

        public FrmDataDeal()
        {
            InitializeComponent();
        }

        private void FrmDataDeal_Load(object sender, EventArgs e)
        {
            toolBtnExport.Visible = true;
            toolBtnExport.Text = "导出进度";
            toolBtnExport.Click += toolBtnExport_Click;

            toolBtnImport.Visible = true;
            toolBtnImport.Text = "导入进度";
            toolBtnImport.Click += toolBtnImport_Click;

            toolBtnSave.Visible = true;
            toolBtnSave.Text = "入库文件";
            toolBtnSave.Click += toolBtnSave_Click;
            
            toolBtnRefresh.Visible = true;
            toolBtnRefresh.Click += toolBtnRefresh_Click;

            toolBtnVerify.Visible = true;
            toolBtnVerify.Click += toolBtnVerify_Click;
            toolBtnRefresh.PerformClick();

            //toolStrip1.Visible = false;
            toolBtnRun.Visible = true;
            toolBtnRun.Click += toolBtnRun_Click;

            toolBtnStop.Visible = true;
            toolBtnStop.Click += toolBtnStop_Click;

            WorkSpace.GetInstance().TaskPauseEvent += TaskPauseEventHandler;
            WorkSpace.GetInstance().TaskResumeEvent += TaskResumeEventHandler;


            if (PublicObject.CurTask.state == (int)UniRlv.COL.task_state.TS_RUN)
            {
                toolBtnStop.Enabled = true;
                toolBtnRun.Enabled = false;
            }
            else
            {
                toolBtnStop.Enabled = false;
                toolBtnRun.Enabled = true;
            }

            backgroundWorker1 = new BackgroundWorker();
            backgroundWorker1.WorkerReportsProgress = true;
            backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork);
            backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted);
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.Cursor = Cursors.Default;

            progBar.Close();

            if (e.Result != null)
            {
                ShowErrorMessageBox("出现错误", e.Result.ToString());
            }
            else if (e.Cancelled)
            {
                MessageBox.Show("操作取消");
            }
            else
            {
                string msg = "";

                PublicObject.CurTask.verifyer = txtVerifyer.Text.Trim();
                PublicObject.CurTask.operateDate = dtpOpr.Value;
                PublicObject.CurTask.produceDate = dtpMAF.Value;
                PublicObject.CurTask.yxq = dtpYQW.Value;

                WorkSpace.GetInstance().FinishTask(task_state.TS_VERIFIED, ref msg);
                FrmMain.GetInstance().SwitchFormByModuleName("TaskRun");
            }

            
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            string msg = string.Empty;

            worker.ReportProgress(0, "获取任务数据...\r\n");

            XmlDocument doc = GetWareHourseInXm(true, ref msg);

            if (doc != null)
            {

                List<Dictionary<string, object>> ld;
                DataTable dt;

                //保存顺序和导出顺序一致，二次扫描时与扫描顺序不一定一样
                //2020-02-26 审核保存到数据库后二级码的一次扫描和二次扫描序号一样，其实就是二次扫描没有意义了
                List<CodeInfo> codes = new List<CodeInfo>();
                CodeInfo code;

                //删除原已审核数据：非常重要
                bool bRes = false;

                worker.ReportProgress(1, "删除旧数据...\r\n");

                msg = "";
                bRes = DALOpr.ExecuteNonQueryTran(string.Format("delete from CodeInfo where taskid={0}|delete from CodeInfoSingle where taskid={1}",
                    PublicObject.CurTask.ID, PublicObject.CurTask.ID), ref msg);

                if (!bRes)
                {
                    e.Result = "删除旧数据失败：" + msg;

                    Program.AppendExceptionLog("审核任务时删除旧数据失败：" + msg);
                    return;
                }

                if (codes1.Count > 0)
                {
                    worker.ReportProgress(2, "重组一级码...\r\n");

                    for (int i = 0; i < codes1.Count; i++)
                    {
                        code = PublicObject.arrCode1.FindLast(s => s.code.Equals(codes1[i]));
                        code.serialNumber = i + 1;

                        codes.Add(code);
                    }

                    worker.ReportProgress(3, "一级码转换为数据表结构...\r\n");

                    ld = EntityHelper.GetDicDatas(codes);
                    dt = ld.ToDataTable();
                    dt.TableName = "CodeInfo";

                    worker.ReportProgress(4, "一级码写入数据库...\r\n");
                    bRes = DALOpr.ExcuteBulkCopy("CodeInfo", dt, ref msg);

                    if (!bRes)
                    {
                        e.Result = "审核一级码失败：" + msg;
                        Program.AppendExceptionLog("审核一级码失败：" + msg);
                        return;
                    }

                    //原始数据
                    //ld = EntityHelper.GetDicDatas(PublicObject.arrCode1);
                    //dt = ld.ToDataTable();
                    //dt.TableName = "CodeInfoSingle";
                    //bRes = DALOpr.ExcuteBulkCopy("CodeInfoSingle", dt, ref msg);
                    //if (!bRes)
                    //{
                    //    ShowErrorMessageBox("出现错误", "审核一级码失败：" + msg);
                    //    Program.AppendExceptionLog("审核一级码失败：" + msg);
                    //    return;
                    //}

                    worker.ReportProgress(85, "更新关联数据...\r\n");

                    //更新关联数据
                    if (PublicObject.CodeRlt.Count > 0)
                    {//有关联数据
                        DALOpr.UpdateRltData(codes1, PublicObject.CurTask.batch, PublicObject.CurTask.pzwh, ref msg);
                    }

                }

                worker.ReportProgress(95, "二级码写入数据库...\r\n");

                if (codes2.Count > 0)
                {
                    codes.Clear();

                    for (int i = 0; i < codes2.Count; i++)
                    {
                        code = PublicObject.arrCode2.FindLast(s => s.code.Equals(codes2[i]));
                        code.serialNumber = i + 1;
                        code.serialNumber2 = code.serialNumber;
                        codes.Add(code);
                    }

                    ld = EntityHelper.GetDicDatas(codes);
                    dt = ld.ToDataTable();
                    dt.TableName = "CodeInfo";
                    bRes = DALOpr.ExcuteBulkCopy("CodeInfo", dt, ref msg);
                    if (!bRes)
                    {
                        e.Result = "审核二级码失败：" + msg;
                        Program.AppendExceptionLog("审核二级码失败：" + msg);
                        return;
                    }

                    //原始数据
                    //ld = EntityHelper.GetDicDatas(PublicObject.arrCode2);
                    //dt = ld.ToDataTable();
                    //dt.TableName = "CodeInfoSingle";
                    //bRes = DALOpr.ExcuteBulkCopy("CodeInfoSingle", dt, ref msg);

                    //if (!bRes)
                    //{
                    //    ShowErrorMessageBox("出现错误", "审核二级码失败：" + msg);
                    //    Program.AppendExceptionLog("审核二级码失败：" + msg);
                    //    return;
                    //}
                }

                worker.ReportProgress(98, "三级码写入数据库...\r\n");
                if (codes3.Count > 0)
                {
                    codes.Clear();

                    for (int i = 0; i < codes3.Count; i++)
                    {
                        code = PublicObject.arrCode3.FindLast(s => s.code.Equals(codes3[i]));
                        code.serialNumber = i + 1;
                        codes.Add(code);
                    }

                    ld = EntityHelper.GetDicDatas(codes);
                    dt = ld.ToDataTable();
                    dt.TableName = "CodeInfo";
                    bRes = DALOpr.ExcuteBulkCopy("CodeInfo", dt, ref msg);

                    if (!bRes)
                    {
                        e.Result = "审核三级码失败：" + msg;
                        Program.AppendExceptionLog("审核三级码失败：" + msg);
                        return;
                    }

                    //原始数据
                    //ld = EntityHelper.GetDicDatas(PublicObject.arrCode3);
                    //dt = ld.ToDataTable();
                    //dt.TableName = "CodeInfoSingle";
                    //bRes = DALOpr.ExcuteBulkCopy("CodeInfoSingle", dt, ref msg);

                    //if (!bRes)
                    //{
                    //    ShowErrorMessageBox("出现错误", "审核三级码失败：" + msg);
                    //    Program.AppendExceptionLog("审核三级码失败：" + msg);
                    //    return;
                    //}
                }

                worker.ReportProgress(99, "四级码写入数据库...\r\n");
                if (codes4.Count > 0)
                {
                    codes.Clear();

                    for (int i = 0; i < codes4.Count; i++)
                    {
                        code = PublicObject.arrCode4.FindLast(s => s.code.Equals(codes4[i]));
                        code.serialNumber = i + 1;
                        codes.Add(code);
                    }

                    ld = EntityHelper.GetDicDatas(codes);
                    dt = ld.ToDataTable();
                    dt.TableName = "CodeInfo";
                    bRes = DALOpr.ExcuteBulkCopy("CodeInfo", dt, ref msg);

                    if (!bRes)
                    {
                        e.Result = "审核四级码失败：" + msg;
                        Program.AppendExceptionLog("审核四级码失败：" + msg);
                        return;
                    }

                    //原始数据
                    //ld = EntityHelper.GetDicDatas(PublicObject.arrCode4);
                    //dt = ld.ToDataTable();
                    //dt.TableName = "CodeInfoSingle";
                    //bRes = DALOpr.ExcuteBulkCopy("CodeInfoSingle", dt, ref msg);

                    //if (!bRes)
                    //{
                    //    ShowErrorMessageBox("出现错误", "审核四级码失败：" + msg);
                    //    Program.AppendExceptionLog("审核四级码失败：" + msg);
                    //    return;
                    //}
                }
                //if (!b)
                //{
                //    Console.WriteLine(msg);
                //}
                worker.ReportProgress(100, "审核完成！\r\n");
                e.Result = null;
            }
            else
            {
                e.Result = "XML转换失败：" + msg;
            }

            
        }

        private void TaskResumeEventHandler(object sender, EventArgs e)
        {
            toolBtnRun.Enabled = false;
            toolBtnStop.Enabled = true;
        }

        private void TaskPauseEventHandler(object sender, EventArgs e)
        {
            toolBtnRun.Enabled = true;
            toolBtnStop.Enabled = false;
        }

        private void toolBtnStop_Click(object sender, EventArgs e)
        {
            WorkSpace.GetInstance().PauseTask();
        }

        private void toolBtnRun_Click(object sender, EventArgs e)
        {
            WorkSpace.GetInstance().ResumeTask();
        }

        void toolBtnVerify_Click(object sender, EventArgs e)
        {
            string msg = string.Empty;

            if (PublicObject.CurTask.state == (int)task_state.TS_RUN)
            {
                ShowInfoMessageBox("提示", "先暂停生产任务！");
                return;
            }

            if (txtVerifyer.Text.Trim().Length == 0)
            {
                ShowInfoMessageBox("提示", "审核人不能为空！");
                return;
            }

            if (PublicObject.CurTask.state != (int)task_state.TS_EXPORTED && PublicObject.CurTask.exportTimes==0)
            {
                msg = "数据尚未导出，确定直接审核？";
            }
            else
            {
                msg = "审核数据后将结束任务，并自动永久保存数据，确认审核？";
            }

            if (MessageBox.Show(this, msg, "请确定", MessageBoxButtons.OKCancel, 
                MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == System.Windows.Forms.DialogResult.OK)
            {
                

                this.Cursor = Cursors.WaitCursor;

                this.backgroundWorker1.RunWorkerAsync(); // 运行 backgroundWorker 组件

                progBar = new FrmProcessBar(this.backgroundWorker1);// 显示进度条窗体
                progBar.Text = "审核任务信息";
                progBar.Show(this);

                
            }
        }

        void toolBtnRefresh_Click(object sender, EventArgs e)
        {
            txtBatch.Text = PublicObject.CurTask.batch;
            txtTYM.Text = PublicObject.CurTask.tym;
            txtPZWH.Text = PublicObject.CurTask.pzwh;
            txtSpec.Text = PublicObject.CurTask.gg;
            txtMinTagUnit.Text = PublicObject.CurTask.minTagUnit;
            txtMinPackUnit.Text = PublicObject.CurTask.minPackUnit;
            txtMinUnitRatio.Text = PublicObject.CurTask.tagPackRatio.ToString();
            txtMinTagGG.Text = PublicObject.CurTask.minTagGG;
            txtRatio.Text = PublicObject.CurTask.tagRatio;
            txtOpr.Text = PublicObject.CurTask.oprator;
            txtCreator.Text = PublicObject.CurTask.creator;
            dtpMAF.Value = PublicObject.CurTask.produceDate;
            dtpOpr.Value = PublicObject.CurTask.operateDate;

            lbCode1.Text = PublicObject.arrCode1.Count.ToString();
            lbCode2.Text = PublicObject.arrCode2.Count.ToString();
            lbCode3.Text = PublicObject.arrCode3.Count.ToString();
            lbCode4.Text = PublicObject.arrCode4.Count.ToString();

            lbPick1.Text = PublicObject.Picks1.ToString();

            dtpYQW.Value = AppHelper.SYZSGetYXQ(PublicObject.CurTask.produceDate, (date_unit)PublicObject.CurProduct.yxqdw, PublicObject.CurProduct.yxq);

            if (PublicObject.bSecond)
            {
                lbScanTwice.Text = CodePrcUtility.GetScanTwiceQty().ToString();
            }
            else
            {
                lbTipScanTwice.Visible = false;
                lbScanTwice.Visible = false;
            }

            lbNormal.Text = CodePrcUtility.GetNormalQty().ToString();
            lbUnpack.Text = CodePrcUtility.GetUnpackQty().ToString();
            lbZero.Text = CodePrcUtility.GetZeroAllQty().ToString();
        }

        private void toolBtnSave_Click(object sender, EventArgs e)
        {
            if (PublicObject.CurTask.state == (int)task_state.TS_RUN)
            {
                ShowInfoMessageBox("提示", "先暂停生产任务！");
                return;
            }

            string nameRule = ConfigurationHelper.AppGetString("outputInFileName");

            string err = "";
            ProductionTask t = PublicObject.CurTask;
            ProductInfo pi = PublicObject.CurProduct;

            if (string.IsNullOrEmpty(nameRule))
            {
                nameRule = $"InData_{t.batch}_一级码{PublicObject.arrCode1.Count}条_{DateTime.Now.ToString("yyyyMMdd-HHmmss")}";
            }

            if (pi != null)
            {
                nameRule = nameRule.Replace("{itemid}", pi.itemid);
                nameRule = nameRule.Replace("{spm}", pi.spm);
            }

            nameRule = nameRule.Replace("{qty}", PublicObject.arrCode1.Count.ToString());
            nameRule = nameRule.Replace("{batch}", t.batch);
            nameRule = nameRule.Replace("{unit}", t.minTagUnit);
            nameRule = nameRule.Replace("{taskid}", t.ID.ToString());
            nameRule = nameRule.Replace("{now}", DateTime.Now.ToString("yyyyMMdd_HHmmss"));
            nameRule = nameRule.Replace("{tym}", t.tym);
            nameRule = nameRule.Replace("{gg}", t.gg);
            nameRule = nameRule.Replace("{taskNO}", t.number.ToString());

            SaveFileDialog sfd = new SaveFileDialog();
            sfd.AddExtension = true;
            sfd.DefaultExt = "xml";
            sfd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
            sfd.FileName = string.Format("{0}.xml", nameRule);
            sfd.Filter = "(*.xml)XML文件|*.xml";
            sfd.Title = "保存入库文件";

            if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string msg = string.Empty;
                this.Cursor = Cursors.WaitCursor;
                //#region 入库文件还需分割
                //try
                //{
                //    XmlDocument doc = GetWareHourseInXm(false, ref msg);

                //    if (doc != null)
                //    {
                //        using (StreamWriter sw = new StreamWriter(sfd.FileName))
                //        {
                //            XmlWriterSettings settings = new XmlWriterSettings();
                //            settings.Indent = true;
                //            settings.IndentChars = "  ";
                //            XmlWriter xmlWriter = XmlWriter.Create(sw, settings);
                //            doc.Save(xmlWriter);
                //            xmlWriter.Close();

                //            PublicObject.CurTask.state = (int)task_state.TS_EXPORTED;
                //            PublicObject.CurTask.exportTimes++;
                //            PublicObject.CurTask.produceDate = dtpMAF.Value;

                //            msg = string.Empty;

                //            ProductInfo p = DALOpr.QueryByID<ProductInfo>(PublicObject.CurTask.productID.ToString(), ref msg);

                //            if (p!=null)
                //            {
                //                PublicObject.CurTask.yxq = AppHelper.SYZSGetYXQ(PublicObject.CurTask.produceDate, (date_unit)p.yxqdw, p.yxq);
                //            }

                //            MessageBox.Show("保存成功！");
                //        }
                //    }
                //    else
                //    {
                //        MessageBox.Show(this, msg, "出现错误");
                //    }
                //}
                //catch (Exception exp)
                //{

                //    MessageBox.Show(this, msg, "出现错误:" + exp.Message);
                //}
                //#endregion

                #region 入库文件导出并自动分割
                try
                {

                    if (GetWareHourseInXm2(sfd.FileName, ref msg))
                    {
                        PublicObject.CurTask.state = (int)task_state.TS_EXPORTED;
                        PublicObject.CurTask.exportTimes++;
                        PublicObject.CurTask.produceDate = dtpMAF.Value;
                        PublicObject.CurTask.operateDate = dtpOpr.Value;

                        msg = string.Empty;

                        ProductInfo p = DALOpr.QueryByID<ProductInfo>(PublicObject.CurTask.productID.ToString(), ref msg);

                        if (p != null)
                        {
                            PublicObject.CurTask.yxq = AppHelper.SYZSGetYXQ(PublicObject.CurTask.produceDate, (date_unit)p.yxqdw, p.yxq);
                        }

                        MessageBox.Show("保存成功！");
                    }
                    else
                    {
                        MessageBox.Show(this, msg, "出现错误");
                    }
                }
                catch (Exception exp)
                {

                    MessageBox.Show(this, msg, "出现错误:" + exp.Message);
                }
                #endregion

                this.Cursor = Cursors.Default;
            }
        }

        private void toolBtnExport_Click(object sender, EventArgs e)
        {
            if (PublicObject.CurTask.state == (int)task_state.TS_RUN)
            {
                ShowInfoMessageBox("提示", "先暂停生产任务！");
                return;
            }

            SaveFileDialog sfd = new SaveFileDialog();
            sfd.AddExtension = true;
            sfd.DefaultExt = "xml";
            sfd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
            sfd.FileName = string.Format("进度文件_{0}.xml", DateTime.Now.ToString("yyyyMMdd_HHmmss"));
            sfd.Filter = "(*.xml)XML文件|*.xml";
            sfd.Title = "导出扫描进度";

            if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.Cursor = Cursors.WaitCursor;

                if (ExportScanProccess(sfd.FileName))
                {
                    MessageBox.Show(this, "导出扫描进度成功！");
                }
                else
                {
                    MessageBox.Show(this, "导出失败", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
                }

                this.Cursor = Cursors.Default;
            }
        }

        private void toolBtnImport_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.AddExtension = true;
            ofd.DefaultExt = "xml";
            ofd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
            ofd.Filter = "(*.xml)XML文件|*.xml";
            ofd.Title = "导入扫描进度";

            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.Cursor = Cursors.WaitCursor;

                string msg = string.Empty;
                if (ImportScanProccess(ofd.FileName, ref msg))
                {
                    toolBtnRefresh.PerformClick();

                    WorkSpace.GetInstance().RefreshCodeQty();

                    MessageBox.Show(this, "加载扫描进度成功！");
                }
                else
                {
                    ShowErrorMessageBox("导入失败", msg);
                }

                this.Cursor = Cursors.Default;
            }
        }

        public static bool ExportScanProccess(string path)
        {
            try
            {
                ScanProccess sp = ScanProccess.GetInstance();
                sp.Codes11.Clear();
                sp.Codes12.Clear();
                sp.Codes2.Clear();
                sp.Codes3.Clear();
                sp.Codes4.Clear();
                sp.CurTask = (ProductionTask)PublicObject.CurTask.Clone();
                sp.Codes11.AddRange(PublicObject.arrCode1.GetList(0));
                sp.CurTask.scanQuantity = sp.Codes11.Count;
                if (PublicObject.arrCode1.bMergeOne)
                {
                    sp.Codes12.AddRange(PublicObject.arrCode1.GetList(1));
                    sp.CurTask.scanQuantity += sp.Codes12.Count;
                }

                sp.Codes2.AddRange(PublicObject.arrCode2);
                sp.Codes3.AddRange(PublicObject.arrCode3);
                sp.Codes4.AddRange(PublicObject.arrCode4);


                sp.Picks1 = PublicObject.Picks1;
                sp.Picks2 = PublicObject.Picks2;
                sp.Picks3 = PublicObject.Picks3;


                return XmlHelper.XmlSerialize(path, sp, sp.GetType());
            }
            catch (Exception exp)
            {
                return false;
            }


        }

        public static bool ImportScanProccess(string path, ref string msg)
        {
            ScanProccess sp = (ScanProccess)XmlHelper.XmlDeserialize(path, typeof(ScanProccess));

            if (sp == null)
            {
                msg = "导入失败：无法获取进度文件数据";
                return false;
            }

            if (sp.Codes11.Count==0 && sp.Codes12.Count == 0)
            {//可能是老版本进度文件
                Widget.Old.ScanProccess spCode1 = (Widget.Old.ScanProccess)XmlHelper.XmlDeserialize(path, typeof(Widget.Old.ScanProccess));

                if (spCode1!=null)
                {
                    sp.Codes11.AddRange(spCode1.Codes1.FindAll(s=>s.subDeviceNumber == 0));
                    sp.Codes12.AddRange(spCode1.Codes1.FindAll(s => s.subDeviceNumber != 0));
                }

            }
            //增加查重
            for (int i = 0; i < sp.Codes11.Count; i++)
            {
                if (CodePrcUtility.FindCode(sp.Codes11[i].code) != null || PublicObject.CodeScanned.Contains(sp.Codes11[i].code))
                {
                    msg = "一级码数据重复，条码内容=" + sp.Codes11[i].code;
                    return false;
                }
            }

            for (int i = 0; i < sp.Codes12.Count; i++)
            {
                if (CodePrcUtility.FindCode(sp.Codes12[i].code) != null || PublicObject.CodeScanned.Contains(sp.Codes12[i].code))
                {
                    msg = "一级码数据重复，条码内容=" + sp.Codes12[i].code;
                    return false;
                }
            }

            for (int i = 0; i < sp.Codes2.Count; i++)
            {
                if (CodePrcUtility.FindCode(sp.Codes2[i].code) != null || PublicObject.CodeScanned.Contains(sp.Codes2[i].code))
                {
                    msg = "二级码数据重复，条码内容=" + sp.Codes2[i].code;
                    return false;
                }
            }

            for (int i = 0; i < sp.Codes3.Count; i++)
            {
                if (CodePrcUtility.FindCode(sp.Codes3[i].code) != null || PublicObject.CodeScanned.Contains(sp.Codes3[i].code))
                {
                    msg = "三级码数据重复，条码内容=" + sp.Codes3[i].code;
                    return false;
                }
            }

            for (int i = 0; i < sp.Codes4.Count; i++)
            {
                if (CodePrcUtility.FindCode(sp.Codes4[i].code) != null || PublicObject.CodeScanned.Contains(sp.Codes4[i].code))
                {
                    msg = "四级码数据重复，条码内容=" + sp.Codes4[i].code;
                    return false;
                }
            }

            if (sp != null && sp.CurTask.batch.Equals(PublicObject.CurTask.batch) && sp.CurTask.pzwh.Equals(PublicObject.CurTask.pzwh))
            {


                PublicObject.arrCode1.GetList(1).AddRange(sp.Codes12);
                PublicObject.arrCode1.GetList(0).AddRange(sp.Codes11);

                PublicObject.arrCode2.AddRange(sp.Codes2);
                PublicObject.arrCode3.AddRange(sp.Codes3);
                PublicObject.arrCode4.AddRange(sp.Codes4);

                return true;

            }
            else
            {
                msg = "xml文件非本任务进度" ;

                return false;
            }
        }

        public XmlDocument GetWareHourseInXm(bool bOnlyListCode, ref string msg)
        {
            XmlDocument xmlDoc = GenInXmlHead(PublicObject.CurTask, dtpMAF.Value, dtpOpr.Value);

            codes1.Clear();
            codes2.Clear();
            codes3.Clear();
            codes4.Clear();

            int[] ratios = AppHelper.GetLevelRatios(PublicObject.CurTask.tagRatio);
            int ratio32=0, ratio21=0, ratio43=0;

            switch (PublicObject.CurTask.tagLevel)
            {
                case 4:
                    ratio43 = ratios[0];
                    ratio32 = ratios[1];
                    ratio21 = ratios[2];break;
                case 3:
                    ratio32 = ratios[0];
                    ratio21 = ratios[1];break;
                case 2:
                    ratio21 = ratios[0];break;
                case 1:
                    break;
                default:
                    msg = "包装级别不支持：级别=" + PublicObject.CurTask.tagLevel;
                    return null;
            }
            
            
            if (PublicObject.CurTask.tagLevel>2)
            {
                if (CodePrcUtility.GetZeroQty() > 0)
                {
                    msg = "不允许有散装一级码，请继续扫描小包装条码或删除一级码！";
                    return null;
                }

                codes3.AddRange(PublicObject.arrCode3.ConvertAll<string>(s => s.code));
                codes4.AddRange(PublicObject.arrCode4.ConvertAll<string>(s => s.code));

                if (PublicObject.bSecond)
                {
                    foreach (var item in PublicObject.arrCode2)
	                {
		                if (CodePrcUtility.FindCodePos2(item)<0)
	                    {
                            msg = string.Format("包含尚未二次扫描的条码：{0}, 一次扫描序号={1}，二次扫描序号={2}", item.code, CodePrcUtility.FindCodePos(item), CodePrcUtility.FindCodePos2(item));
		                    return null;
	                    }
	                }

                    List<string> arrOrderCode2 = PublicObject.arrCode2.ConvertAll<string>(s => s.code);
                    			
                    int idx;
                    
                    List<CodeInfo> arrTmp;

			        for (int i=0; i<codes3.Count; i++)
			        {
                        arrTmp = CodePrcUtility.FindArrayByPos2(i*ratio32, ratio32);

                        //注释掉下面代码，是因为允许出现零三级包装
				        //if (arrTmp.Count!=ratio32)
				        //{
					       // msg = string.Format("通过二次扫描序号找不到整包装：找到数量{0}，三级二级比例{1}，三级码位置{2}，三级码数量={3}，二级码数量={4}\n", 
						      //  arrTmp.Count, ratio32, i+1, codes3.Count, arrOrderCode2.Count);
					       // return null;
				        //}

				        for (int j=0; j<arrTmp.Count; j++)
				        {
                            codes2.Add(arrTmp[j].code);
                            idx = CodePrcUtility.FindCodePos(arrTmp[j]);

					        for (int k=idx*ratio21; k<(idx+1)*ratio21 && k<PublicObject.arrCode1.Count; k++)
					        {
                                codes1.Add(PublicObject.arrCode1[k].code);
					        }
				        }
			        }

                    //三级以下非整包装数据
                    arrTmp = CodePrcUtility.FindArrayByPos2(codes3.Count * ratio32);
                    for (int j = 0; j < arrTmp.Count; j++)
                    {
                        codes2.Add(arrTmp[j].code);
                        idx = CodePrcUtility.FindCodePos(arrTmp[j]);

                        for (int k = idx * ratio21; k < (idx + 1) * ratio21 && k < PublicObject.arrCode1.Count; k++)
                        {
                            codes1.Add(PublicObject.arrCode1[k].code);
                        }
                    }

                    //一级码未包装
                    for (int i = 0; i < PublicObject.arrCode1.Count; i++)
                    {
                        if (!codes1.Contains(PublicObject.arrCode1[i].code))
                        {
                            codes1.Add(PublicObject.arrCode1[i].code);
                        }
                    }

                }
                else
                {//已经包含非整包装数据
                    codes1.AddRange(PublicObject.arrCode1.MyConvertAll<string>(s => s.code));
                    codes2.AddRange(PublicObject.arrCode2.ConvertAll<string>(s => s.code));
                }
            }
            else
            {//已经包含非整包装数据
                codes1.AddRange(PublicObject.arrCode1.MyConvertAll<string>(s => s.code));
                codes2.AddRange(PublicObject.arrCode2.ConvertAll<string>(s => s.code));
            }

            if (bOnlyListCode)
            {
                return xmlDoc;
            }
            else
            {
                //------------<Data code=瓶码/>
                bool bOK = false;


                switch (PublicObject.CurTask.tagLevel)
                {
                    case 1:
                        bOK = SaveCode1(xmlDoc, codes1); break;
                    case 2:
                        bOK = SaveCode12(xmlDoc, ratio21, codes1, codes2); break;
                    case 3:
                        bOK = SaveCode123(xmlDoc, ratio21, ratio32, codes1, codes2, codes3); break;
                    case 4:
                        bOK = SaveCode1234(xmlDoc, ratio21, ratio32, ratio43, codes1, codes2, codes3, codes4); break;
                    default:
                        msg = "包装级别不支持：级别=" + PublicObject.CurTask.tagLevel;
                        return null;
                }

                if (bOK)
                {
                    return xmlDoc;
                }
                else
                {
                    return null;
                }
            }

            
        }

        public bool GetWareHourseInXm2(string path, ref string msg)
        {
            XmlDocument xmlDoc =  GetWareHourseInXm(true, ref msg);

            if (xmlDoc == null)
            {
                return false;
            }

            //codes1.Clear();
            //codes2.Clear();
            //codes3.Clear();
            //codes4.Clear();

            int[] ratios = AppHelper.GetLevelRatios(PublicObject.CurTask.tagRatio);
            int ratio32 = 0, ratio21 = 0, ratio43 = 0;

            switch (PublicObject.CurTask.tagLevel)
            {
                case 4:
                    ratio43 = ratios[0];
                    ratio32 = ratios[1];
                    ratio21 = ratios[2]; break;
                case 3:
                    ratio32 = ratios[0];
                    ratio21 = ratios[1]; break;
                case 2:
                    ratio21 = ratios[0]; break;
                case 1:
                    break;
                default:
                    msg = "包装级别不支持：级别=" + PublicObject.CurTask.tagLevel;
                    return false;
            }


            //if (PublicObject.CurTask.tagLevel > 2)
            //{

            //    codes3.AddRange(PublicObject.arrCode3.ConvertAll<string>(s => s.code));
            //    codes4.AddRange(PublicObject.arrCode4.ConvertAll<string>(s => s.code));

            //    if (PublicObject.bSecond)
            //    {
            //        foreach (var item in PublicObject.arrCode2)
            //        {
            //            if (CodePrcUtility.FindCodePos2(item) < 0)
            //            {
            //                msg = string.Format("包含尚未二次扫描的条码：{0}, 一次扫描序号={1}，二次扫描序号={2}", item.code, CodePrcUtility.FindCodePos(item), CodePrcUtility.FindCodePos2(item));
            //                return false;
            //            }
            //        }

            //        List<string> arrOrderCode2 = PublicObject.arrCode2.ConvertAll<string>(s => s.code);

            //        int idx;

            //        List<CodeInfo> arrTmp;

            //        for (int i = 0; i < codes3.Count; i++)
            //        {
            //            arrTmp = CodePrcUtility.FindArrayByPos2(i * ratio32, ratio32);

            //            for (int j = 0; j < arrTmp.Count; j++)
            //            {
            //                codes2.Add(arrTmp[j].code);
            //                idx = CodePrcUtility.FindCodePos(arrTmp[j]);

            //                for (int k = idx * ratio21; k < (idx + 1) * ratio21 && k < PublicObject.arrCode1.Count; k++)
            //                {
            //                    codes1.Add(PublicObject.arrCode1[k].code);
            //                }
            //            }
            //        }

            //        //三级以下非整包装数据
            //        arrTmp = CodePrcUtility.FindArrayByPos2(codes3.Count * ratio32);
            //        for (int j = 0; j < arrTmp.Count; j++)
            //        {
            //            codes2.Add(arrTmp[j].code);
            //            idx = CodePrcUtility.FindCodePos(arrTmp[j]);

            //            for (int k = idx * ratio21; k < (idx + 1) * ratio21 && k < PublicObject.arrCode1.Count; k++)
            //            {
            //                codes1.Add(PublicObject.arrCode1[k].code);
            //            }
            //        }

            //        //一级码未包装
            //        for (int i = 0; i < PublicObject.arrCode1.Count; i++)
            //        {
            //            if (!codes1.Contains(PublicObject.arrCode1[i].code))
            //            {
            //                codes1.Add(PublicObject.arrCode1[i].code);
            //            }
            //        }

            //    }
            //    else
            //    {//已经包含非整包装数据
            //        codes1.AddRange(PublicObject.arrCode1.MyConvertAll<string>(s => s.code));
            //        codes2.AddRange(PublicObject.arrCode2.ConvertAll<string>(s => s.code));
            //    }
            //}
            //else
            //{//已经包含非整包装数据
            //    codes1.AddRange(PublicObject.arrCode1.MyConvertAll<string>(s => s.code));
            //    codes2.AddRange(PublicObject.arrCode2.ConvertAll<string>(s => s.code));
            //}

            //父码必数量必须可以涵盖子码

            InFileGenAndSplit ifgs = new InFileGenAndSplit();
            ifgs.codes1 = codes1;
            ifgs.codes2 = codes2;
            ifgs.codes3 = codes3;
            ifgs.codes4 = codes4;
            ifgs.Path2Save = path;
            ifgs.ratio21 = ratio21;
            ifgs.ratio32 = ratio32;
            ifgs.ratio43 = ratio43;
            ifgs.tmOpr = dtpOpr.Value;
            ifgs.tmProduce = dtpMAF.Value;
            ifgs.task = PublicObject.CurTask;

            bool bOK = ifgs.SaveInFile();
            msg = ifgs.ErrorString;

            return bOK;
        }

        public static XmlDocument GenInXmlHead(ProductionTask t, DateTime tmProduce, DateTime tmOpr)
        {
            XmlDocument xmlDoc = new XmlDocument();

            //创建类型声明节点  
            XmlNode node = xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", "");
            xmlDoc.AppendChild(node);
            //创建根节点  
            XmlElement root = xmlDoc.CreateElement("DataList");
            xmlDoc.AppendChild(root);
            root.SetAttribute("corpName", PublicObject.CurCompany.name);
            root.SetAttribute("manCode", "19060101");
            root.SetAttribute("dataType", "wareHouseIn");
            root.SetAttribute("version", "1.0");
            root.SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
            root.SetAttribute("xsi:noNamespaceSchemaLocation", "兽药产品入库数据_生产企业.xsd");


            //Product 节点
            XmlElement eleProduct = xmlDoc.CreateElement("Product");
            eleProduct.SetAttribute("productName", t.tym);
            eleProduct.SetAttribute("pzwh", t.pzwh);
            eleProduct.SetAttribute("packing", t.minTagGG);
            root.AppendChild(eleProduct);

            //batch节点
            XmlElement eleBatch = xmlDoc.CreateElement("Batch");
            eleBatch.SetAttribute("batchNo", t.batch);
            eleBatch.SetAttribute("specification", t.gg);
            eleBatch.SetAttribute("minPackUnit", t.minPackUnit);
            eleBatch.SetAttribute("minTagUnit", t.minTagUnit);
            eleBatch.SetAttribute("tagPackRatio", t.tagPackRatio.ToString());
            eleBatch.SetAttribute("tagRatio", t.tagRatio);
            eleBatch.SetAttribute("produceDate", tmProduce.ToString("yyyy-MM-dd"));
            eleBatch.SetAttribute("operator", t.oprator);
            eleBatch.SetAttribute("oprDate", tmOpr.ToString("yyyy-MM-dd"));
            eleBatch.SetAttribute("count", "0");
            eleBatch.SetAttribute("countUnit", "0");

            eleProduct.AppendChild(eleBatch);

            return xmlDoc;
        }

        public static bool SaveCode1(XmlDocument xmlDoc, IList<string> codes1)
        {
            //code节点
            XmlElement eleCode;
            XmlElement eleBatch;

            eleBatch = xmlDoc.SelectSingleNode("DataList/Product/Batch") as XmlElement;

            foreach (string code in codes1)
            {
                eleCode = xmlDoc.CreateElement("Data");
                eleCode.SetAttribute("code", code);
                eleBatch.AppendChild(eleCode);
            }

            return true;

        }

        public static bool SaveCode12(XmlDocument xmlDoc, int ratio21, IList<string> codes1, IList<string> codes2)
        {
            //code节点
            XmlElement eleCode;
            XmlElement eleBatch;

            eleBatch = xmlDoc.SelectSingleNode("DataList/Product/Batch") as XmlElement;

            int nBox = codes2.Count;
            nBox = nBox > codes1.Count / ratio21 ? codes1.Count / ratio21 : nBox;

            Console.WriteLine("开始导出数据:SaveCode12\r\n");

            for (int i = 0; i < nBox; i++)
            {//先放瓶码，后放箱码
                for (int j = 0; j < ratio21; j++)
                {
                    eleCode = xmlDoc.CreateElement("Data");
                    eleCode.SetAttribute("code", codes1[i * ratio21 + j]);
                    eleBatch.AppendChild(eleCode);
                }

                eleCode = xmlDoc.CreateElement("Data");
                eleCode.SetAttribute("code", codes2[i]);
                eleBatch.AppendChild(eleCode);
            }

            //零散数据
            for (int i = nBox * ratio21; i < (nBox + 1) * ratio21 && i < codes1.Count; i++)
            {
                eleCode = xmlDoc.CreateElement("Data");
                eleCode.SetAttribute("code", codes1[i]);
                eleBatch.AppendChild(eleCode);
            }

            //是否含最后的零箱码
            if (codes2.Count > nBox)
            {
                eleCode = xmlDoc.CreateElement("Data");
                eleCode.SetAttribute("code", codes2[nBox]);
                eleBatch.AppendChild(eleCode);
            }

            return true;

        }

        public static bool SaveCode123(XmlDocument xmlDoc, int ratio21, int ratio32, IList<string> codes1, IList<string> codes2, IList<string> codes3)
        {
            //code节点
            XmlElement eleCode;
            XmlElement eleBatch;

            eleBatch = xmlDoc.SelectSingleNode("DataList/Product/Batch") as XmlElement;
            ////计算导出的箱数量
            int nBox = codes3.Count;

            int nCaseRatio = ratio32;
            int nBtlRatio = ratio21;

            //不允许存在顶级零箱，故最大整包装数量就是顶级码数量
            //nBox = nBox > codes2.Count / nCaseRatio ? codes2.Count / nCaseRatio : nBox;
            //nBox = nBox > codes1.Count / (nBtlRatio * nCaseRatio) ? codes1.Count / (nBtlRatio * nCaseRatio) : nBox;

            Console.WriteLine("开始导出数据:SaveCode123\r\n");

            for (int i = 0; i < nBox; i++)
            {//瓶瓶瓶盒-瓶瓶瓶盒-瓶瓶瓶盒……瓶瓶瓶盒箱
                for (int j = 0; j < nCaseRatio; j++)
                {
                    for (int k = 0; k < nBtlRatio; k++)
                    {
                        eleCode = xmlDoc.CreateElement("Data");
                        eleCode.SetAttribute("code", codes1[i * nCaseRatio * nBtlRatio + j * nBtlRatio + k]);
                        eleBatch.AppendChild(eleCode);
                    }

                    eleCode = xmlDoc.CreateElement("Data");
                    eleCode.SetAttribute("code", codes2[i * nCaseRatio + j]);
                    eleBatch.AppendChild(eleCode);

                }

                eleCode = xmlDoc.CreateElement("Data");
                eleCode.SetAttribute("code", codes3[i]);
                eleBatch.AppendChild(eleCode);
            }

            //零散数据：够两级
            int loopMax;
            for (int j = nBox * nCaseRatio; j < (nBox + 1) * nCaseRatio && j < codes2.Count; j++)
            {
                for (loopMax = j * nBtlRatio; loopMax < (j + 1) * nBtlRatio && loopMax < codes1.Count; loopMax++)
                {
                    eleCode = xmlDoc.CreateElement("Data");
                    eleCode.SetAttribute("code", codes1[loopMax]);
                    eleBatch.AppendChild(eleCode);
                }

                eleCode = xmlDoc.CreateElement("Data");
                eleCode.SetAttribute("code", codes2[j]);
                eleBatch.AppendChild(eleCode);

                if (loopMax == codes1.Count)
                {//已无一级码
                    return true;
                }
            }

            //零散数据：一级尾数

            for (int j = codes2.Count * nBtlRatio; j < (codes2.Count + 1) * nBtlRatio && j < codes1.Count; j++)
            {
                eleCode = xmlDoc.CreateElement("Data");
                eleCode.SetAttribute("code", codes1[j]);
                eleBatch.AppendChild(eleCode);
            }

            return true;

        }

        public static bool SaveCode1234(XmlDocument xmlDoc, int ratio21, int ratio32, int ratio43, IList<string> codes1, IList<string> codes2, IList<string> codes3, IList<string> codes4)
        {
            //code节点
            XmlElement eleCode;
            XmlElement eleBatch;

            eleBatch = xmlDoc.SelectSingleNode("DataList/Product/Batch") as XmlElement;
            ////计算导出的箱数量
            int nBox = codes4.Count;

            //不允许存在顶级零箱，故最大整包装数量就是顶级码数量

            //nBox = nBox > codes3.Count / ratio43 ? codes3.Count / ratio43 : nBox;
            //nBox = nBox > codes2.Count / (ratio32 * ratio43) ? codes2.Count / (ratio32 * ratio43) : nBox;
            //nBox = nBox > codes1.Count / (ratio21 * ratio32 * ratio43) ? codes1.Count / (ratio21 * ratio32 * ratio43) : nBox;

            Console.WriteLine("开始导出数据:SaveCode1234\r\n");

            for (int i = 0; i < nBox; i++)
            {//瓶瓶瓶盒-瓶瓶瓶盒-瓶瓶瓶盒……瓶瓶瓶盒箱-瓶瓶瓶盒-瓶瓶瓶盒-瓶瓶瓶盒……瓶瓶瓶盒箱-瓶瓶瓶盒-瓶瓶瓶盒-瓶瓶瓶盒……瓶瓶瓶盒箱托    四级关联

                for (int j = 0; j < ratio43; j++)
                {
                    for (int k = 0; k < ratio32; k++)
                    {
                        for (int l = 0; l < ratio21; l++)
                        {
                            eleCode = xmlDoc.CreateElement("Data");
                            eleCode.SetAttribute("code", codes1[i * ratio21 * ratio32 * ratio43 + j * ratio21 * ratio32 + k * ratio21 + l]);
                            eleBatch.AppendChild(eleCode);
                        }

                        eleCode = xmlDoc.CreateElement("Data");
                        eleCode.SetAttribute("code", codes2[i * ratio32 * ratio43 + j * ratio32 + k]);
                        eleBatch.AppendChild(eleCode);
                    }

                    eleCode = xmlDoc.CreateElement("Data");
                    eleCode.SetAttribute("code", codes3[i * ratio43 + j]);
                    eleBatch.AppendChild(eleCode);

                }

                eleCode = xmlDoc.CreateElement("Data");
                eleCode.SetAttribute("code", codes4[i]);
                eleBatch.AppendChild(eleCode);
            }

            //零散数据:够三级
            int loopMax1 = 0, loopMax2 = 0;

            for (int j = nBox * ratio43; j < (nBox + 1) * ratio43 && j < codes3.Count; j++)
            {
                for (loopMax2 = j * ratio32; loopMax2 < (j + 1) * ratio32 && loopMax2 < codes2.Count; loopMax2++)
                {
                    for (loopMax1 = loopMax2 * ratio21; loopMax1 < (loopMax2 + 1) * ratio21 && loopMax1 < codes1.Count; loopMax1++)
                    {
                        eleCode = xmlDoc.CreateElement("Data");
                        eleCode.SetAttribute("code", codes1[loopMax1]);
                        eleBatch.AppendChild(eleCode);
                    }

                    eleCode = xmlDoc.CreateElement("Data");
                    eleCode.SetAttribute("code", codes2[loopMax2]);
                    eleBatch.AppendChild(eleCode);

                }

                eleCode = xmlDoc.CreateElement("Data");
                eleCode.SetAttribute("code", codes3[j]);
                eleBatch.AppendChild(eleCode);

                if (loopMax1 == codes1.Count || loopMax2 == codes2.Count)
                {//已无一级码或二级码
                    return true;
                }
            }

            //零散数据：够两级
            int loopMax;
            for (int j = codes3.Count * ratio32; j < (codes3.Count + 1) * ratio32 && j < codes2.Count; j++)
            {
                for (loopMax = j * ratio21; loopMax < (j + 1) * ratio21 && loopMax < codes1.Count; loopMax++)
                {
                    eleCode = xmlDoc.CreateElement("Data");
                    eleCode.SetAttribute("code", codes1[loopMax]);
                    eleBatch.AppendChild(eleCode);
                }

                eleCode = xmlDoc.CreateElement("Data");
                eleCode.SetAttribute("code", codes2[j]);
                eleBatch.AppendChild(eleCode);

                if (loopMax == codes1.Count)
                {//已无一级码
                    return true;
                }
            }

            //零散数据：一级尾数

            for (int j = codes2.Count * ratio21; j < (codes2.Count + 1) * ratio21 && j < codes1.Count; j++)
            {
                eleCode = xmlDoc.CreateElement("Data");
                eleCode.SetAttribute("code", codes1[j]);
                eleBatch.AppendChild(eleCode);
            }

            return true;

        }

        private void dtpMAF_ValueChanged(object sender, EventArgs e)
        {
            dtpYQW.Value = AppHelper.SYZSGetYXQ(dtpMAF.Value, (date_unit)PublicObject.CurProduct.yxqdw, PublicObject.CurProduct.yxq);
        }
    }
}
